package com.coovane.bytetrix.common.util;

import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 随机工具类
 * </p>
 *
 * @author: Hsu
 * @date: 2021/10/14 21:07
 * @copyright: companyName
 * @see
 * @since 1.8
 */
public class RandomUtils {

    public final static char[] CHAR_DIGIT_ARRAY = new char[55];

    static {
        int ignoreCount = 0;
        for (char i = 'a'; i <= 'z'; i++) {
            // 剔除容易混淆的小写字母
            if (i == 'i' || i == 'l' || i == 'o') {
                ignoreCount++;
                continue;
            }
            CHAR_DIGIT_ARRAY[i - 97 - ignoreCount] = i;
        }

        for (char i = 'A'; i <= 'Z'; i++) {
            // 剔除容易混淆的大写字母
            if (i == 'I' || i == 'O') {
                ignoreCount++;
                continue;
            }
            CHAR_DIGIT_ARRAY[i - 39 - ignoreCount] = i;
        }

        for (char i = '2'; i <= '9'; i++) {
            CHAR_DIGIT_ARRAY[i - 3] = i;
        }
    }

    public static void main(String[] args) {
        System.out.println("===========" + randomCode(8));
        System.out.println("===========" + randomIp());
        System.out.println("===========" + randomChinese(3));
        Map<String, String> randomCoordinates = randomCoordinates(null, null, null, null);
        System.out.println("===========[lng,lat]:" + randomCoordinates.get("lng") + "," + randomCoordinates.get("lat"));
    }

    /**
     * 生成某个区间的 随机double
     * digits 保留小数位数
     */
    public static Double randomDouble(int min, int max, int digits) {
        if (digits < 1 || min > max) {
            return null;
        }
        Random ran = new Random();
        // 小数部分
        double decimal = ran.nextDouble();
        // 整数部分
        int integer = randomInt(min, max);
        double num = integer + decimal;
        // 格式化小数，保留固定位数
        String numFormat = "0.";
        for (int i = 0; i < digits; i++) {
            numFormat += "0";
        }
        return Double.parseDouble(new DecimalFormat(numFormat).format(num));
    }

    /**
     * 生成某个区间的 随机Float
     * digits 保留小数位数
     */
    public static Float randomFloat(int min, int max, int digits) {
        if (digits < 1 || min > max) {
            return null;
        }
        Random ran = new Random();
        // 小数部分
        float decimal = ran.nextFloat();
        // 整数部分
        int integer = randomInt(min, max);
        float num = integer + decimal;
        // 格式化小数，保留固定位数
        String numFormat = "0.";
        for (int i = 0; i < digits; i++) {
            numFormat += "0";
        }
        return Float.parseFloat(new DecimalFormat(numFormat).format(num));
    }

    /**
     * 生成某个区间的随机整数
     */
    public static Integer randomInt(int min, int max) {
        if (min > max) {
            return null;
        }
        return new Random().nextInt(max - min) + min;
    }

    /**
     * 在给定的数组中，随机取一个元素
     */
    public static <T> T randomElement(T[] objs) {
        if (objs == null || objs.length == 0) {
            return null;
        }
        Random ran = new Random();
        int ranIndex = ran.nextInt(objs.length);
        return objs[ranIndex];
    }

    /**
     * 生成随机码，默认长度6（已将容易混淆的字母和数字剔除）
     *
     * @param length
     * @return
     */
    public static String randomCode(int length) {
        if (length < 6) {
            length = 6;
        }
        List<Character> characterList = new String(CHAR_DIGIT_ARRAY).chars().mapToObj(c -> (char) c).collect(Collectors.toList());
        // 打乱元素排序，增加反推难度
        Collections.shuffle(characterList);
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append(characterList.get(i));
        }
        return builder.toString();
    }

    /**
     * 生成随机汉字
     */
    public static String randomChinese(int length) {
        if (length < 1) {
            return null;
        }
        StringBuilder builder = new StringBuilder();

        Random random = new Random();
        for (int i = 0; i < length; i++) {
            // 获取高位值
            int heightPos = (176 + Math.abs(random.nextInt(39)));
            // 获取低位值
            int lowPos = (161 + Math.abs(random.nextInt(93)));
            byte[] b = new byte[2];
            b[0] = (new Integer(heightPos).byteValue());
            b[1] = (new Integer(lowPos).byteValue());
            String s = new String(b, Charset.forName("GBK"));
            builder.append(s);
        }

        return builder.toString();
    }

    /**
     * 生成随机IP
     */
    public static String randomIp() {
        String ip = "";
        for (int i = 0; i < 4; i++) {
            int num = randomInt(1, 255);
            num = num < 10 ? num * 10 : num;
            ip += num;
            if (i != 3) {
                ip += ".";
            }
        }
        return ip;
    }

    /**
     * 产生随机经纬度
     * @param minLng 最小经度
     * @param maxLng 最大经度
     * @param minLat 最小纬度
     * @param maxLat 最大纬度
     * @return
     */
    public static Map<String, String> randomCoordinates(Double minLng, Double maxLng, Double minLat, Double maxLat) {
        // 如果传入参数有任意为null，则默认限制在中国外接矩形范围
        if(Objects.isNull(minLng) || Objects.isNull(maxLng) || Objects.isNull(minLat) || Objects.isNull(maxLat)){
            minLng = Double.valueOf("73.5");
            maxLng = Double.valueOf("135");
            minLat = Double.valueOf("4");
            maxLat = Double.valueOf("53.5");
        }
        // 经度范围
        BigDecimal range = new BigDecimal(Math.random() * (maxLng - minLng) + minLng);
        // 小数后6位
        String lng = range.setScale(6, BigDecimal.ROUND_HALF_UP).toString();
        // 纬度范围
        range = new BigDecimal(Math.random() * (maxLat - minLat) + minLat);
        String lat = range.setScale(6, BigDecimal.ROUND_HALF_UP).toString();
        Map<String, String> map = new HashMap<>();
        map.put("lng", lng);
        map.put("lat", lat);
        return map;
    }

}

